#include "tcpclient.h"
#include "VideoStructs.h"
#include <QDebug>

tcpclient::tcpclient(QObject *parent) : QObject(parent) {
    connect(&m_socket, &QTcpSocket::readyRead, this, &tcpclient::onReadyRead);
    connect(&m_socket, &QTcpSocket::disconnected, this, &tcpclient::disconnected);
    connect(&m_socket, QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error),
            this, &tcpclient::onError);
    
    // 初始化当前请求的通道号 
     m_currentRequestChannel = -1;
}

bool tcpclient::connectToServer(const QString &ip, quint16 port) {
    if (isConnected() || isConnecting()) {
        qDebug() << "已经连接或正在连接，直接返回true";
        return true;
    }

    qDebug() << "尝试连接到服务器:" << ip << ":" << port;
    m_socket.connectToHost(QHostAddress(ip), port);

    // 增加连接超时等待
    if (!m_socket.waitForConnected(5000)) {
        qDebug() << "连接超时，错误:" << m_socket.errorString();
        return false;
    }

    qDebug() << "连接成功";
    return true;
}

void tcpclient::sendRegisterStep1(const QString &username) {
    if (!isConnected()) {
        emit registerStep1Result(false, "未连接到服务器");
        return;
    }
    m_registerUsername = username;

    QJsonObject json;
    json["username"] = username;
    QByteArray data = QJsonDocument(json).toJson(QJsonDocument::Compact);

    // 使用与服务器匹配的注册第一步类型（7）
    quint32 netType = qToBigEndian(static_cast<quint32>(TASK_TYPE_REGISTER_SECTION1));
    quint32 netLen = qToBigEndian(static_cast<quint32>(data.size()));

    QByteArray packet;
    packet.append(reinterpret_cast<char*>(&netType), 4);
    packet.append(reinterpret_cast<char*>(&netLen), 4);
    packet.append(data);

    m_socket.write(packet);
    m_socket.flush();
}

void tcpclient::sendRegisterStep2(const QString &encryptedPassword) {
    if (!isConnected()) {
        emit registerStep2Result(false, "未连接到服务器");
        return;
    }
    if (m_registerUsername.isEmpty()) {
        emit registerStep2Result(false, "请先执行注册第一步");
        return;
    }

    QJsonObject json;
    json["username"] = m_registerUsername;
    json["encryptedPassword"] = encryptedPassword;
    QByteArray data = QJsonDocument(json).toJson(QJsonDocument::Compact); // 统一用JSON
    // 使用与服务器匹配的注册第二步类型（10）
    quint32 netType = qToBigEndian(static_cast<quint32>(TASK_TYPE_REGISTER_SECTION2));
    quint32 netLen = qToBigEndian(static_cast<quint32>(data.size()));

    QByteArray packet;
    packet.append(reinterpret_cast<char*>(&netType), 4);
    packet.append(reinterpret_cast<char*>(&netLen), 4);
    packet.append(data);

    m_socket.write(packet);
    m_socket.flush();
}

void tcpclient::sendLoginStep1(const QString &username) {
    if (!isConnected()) {
        emit loginStep1Result(false, "未连接到服务器");
        return;
    }
    m_loginUsername = username;

    QJsonObject json;
    json["username"] = username;
    QByteArray data = QJsonDocument(json).toJson(QJsonDocument::Compact);

    // 使用与服务器匹配的登录第一步类型（1）
    quint32 netType = qToBigEndian(static_cast<quint32>(TASK_TYPE_LOGIN_SECTION1));
    quint32 netLen = qToBigEndian(static_cast<quint32>(data.size()));

    QByteArray packet;
    packet.append(reinterpret_cast<char*>(&netType), 4);
    packet.append(reinterpret_cast<char*>(&netLen), 4);
    packet.append(data);

    m_socket.write(packet);
    m_socket.flush();
}

void tcpclient::sendLoginStep2(const QString &encryptedPassword) {
    qDebug() << "发送登录第二步 - 加密密码:" << encryptedPassword;

    QJsonObject json;
    json["username"] = m_loginUsername;
    json["encryptedPassword"] = encryptedPassword;
    QByteArray data = QJsonDocument(json).toJson(QJsonDocument::Compact);

    quint32 netType = qToBigEndian(static_cast<quint32>(TASK_TYPE_LOGIN_SECTION2));
    quint32 netLen = qToBigEndian(static_cast<quint32>(data.size()));

    QByteArray packet;
    packet.append(reinterpret_cast<char*>(&netType), 4);
    packet.append(reinterpret_cast<char*>(&netLen), 4);
    packet.append(data);

    m_socket.write(packet);
    m_socket.flush();
}

//发送视频流请求
void tcpclient::sendStreamRequest(int cameraId, bool isMainStream)
{
    if(!isConnected()) {
        qWarning() << "未连接到服务器，无法发送视频流请求";
        return;
    }

    qDebug() << "发送视频流请求 - 摄像头ID:" << cameraId << "主码流:" << isMainStream;
    
    // 保存当前请求的通道号
    m_currentRequestChannel = cameraId;

    QJsonObject json;
    json["camera_id"] = cameraId;
    json["stream_type"] = isMainStream ? "main" : "sub";
    QByteArray data = QJsonDocument(json).toJson(QJsonDocument::Compact);

    quint32 netType = qToBigEndian(static_cast<quint32>(TASK_TYPE_STREAM_START_REQUEST));
    quint32 netLen = qToBigEndian(static_cast<quint32>(data.size()));

    QByteArray packet;
    packet.append(reinterpret_cast<char*>(&netType), 4);
    packet.append(reinterpret_cast<char*>(&netLen), 4);
    packet.append(data);

    m_socket.write(packet);
    m_socket.flush();
}

// 发送云台控制请求
void tcpclient::sendPTZControlRequest(int cameraId, const QString &command, int duration) {
    if (!isConnected()) {
        emit ptzControlResult(false, "未连接到服务器");
        return;
    }

    qDebug() << "发送云台控制请求 - 摄像头ID:" << cameraId
             << "命令:" << command
             << "持续时间:" << duration;

    QJsonObject json;
    json["camera_id"] = cameraId;
    json["command"] = command;
    json["duration"] = duration;
    QByteArray data = QJsonDocument(json).toJson(QJsonDocument::Compact);

    quint32 netType = qToBigEndian(static_cast<quint32>(TASK_TYPE_PTZ_CONTROL_REQUEST));
    quint32 netLen = qToBigEndian(static_cast<quint32>(data.size()));

    QByteArray packet;
    packet.append(reinterpret_cast<char*>(&netType), 4);
    packet.append(reinterpret_cast<char*>(&netLen), 4);
    packet.append(data);

    m_socket.write(packet);
    m_socket.flush();
}

bool tcpclient::isConnected() const {
    return m_socket.state() == QAbstractSocket::ConnectedState;
}

bool tcpclient::isConnecting() const {
    return m_socket.state() == QAbstractSocket::ConnectingState ||
            m_socket.state() == QAbstractSocket::HostLookupState;
}

void tcpclient::onReadyRead() {
    // 将新数据添加到缓冲区
    m_readBuffer.append(m_socket.readAll());

    // 处理所有完整的数据包
    while (m_readBuffer.size() >= 8) { // 至少需要8字节的头部
        quint32 netType = *reinterpret_cast<const quint32*>(m_readBuffer.constData());
        quint32 netLen = *reinterpret_cast<const quint32*>(m_readBuffer.constData() + 4);
        quint32 type = qFromBigEndian(netType);
        quint32 len = qFromBigEndian(netLen);

        qDebug() << "解析包 - 类型:" << type << "长度:" << len
                 << "缓冲区剩余:" << m_readBuffer.size();

        if (m_readBuffer.size() < 8 + len) {
            qDebug() << "数据不完整，需要:" << 8 + len << "实际:" << m_readBuffer.size();
            break;
        }
        // 提取数据部分
        QByteArray data = m_readBuffer.mid(8, len);

        // 从缓冲区移除已处理的数据
        m_readBuffer = m_readBuffer.mid(8 + len);

        // 增加日志，打印接收的长度和实际数据
        qDebug() << "接收类型:" << type << "，解析长度:" << len << "，实际数据长度:" << data.size();
        qDebug() << "接收数据内容:" << QString(data);

        // 根据消息类型分发处理（与服务器类型匹配）
        switch (type) {
        case TASK_TYPE_REGISTER_SECTION1_RESP_OK:{
            QString salt = QString::fromUtf8(data);
            qDebug() << "注册第一步返回完整盐值:" << salt;
            emit registerStep1Result(true, "获取盐值成功", salt);
            break;
        }
        case TASK_TYPE_REGISTER_SECTION1_RESP_ERROR: {
            QString errorMsg = QString::fromUtf8(data);
            if (errorMsg.isEmpty()) errorMsg = "用户名已存在";
            emit registerStep1Result(false, errorMsg);
            break;
        }
        case TASK_TYPE_REGISTER_SECTION2_RESP_OK:
            parseRegisterStep2Response(data);
            break;
        case TASK_TYPE_REGISTER_SECTION2_RESP_ERROR:
        {
            QString errorMsg = QString::fromUtf8(data);
            if (errorMsg.isEmpty()) errorMsg = "注册失败";
            emit registerStep2Result(false, errorMsg);
            break;
        }
        case TASK_TYPE_LOGIN_SECTION1_RESP_OK:
        {
            QString fullSalt = QString::fromUtf8(data);
            qDebug() << "登录第一步返回完整盐值:" << fullSalt;
            // 确保盐值格式正确
            if (!fullSalt.startsWith("$1$") || !fullSalt.endsWith("$")) {
                emit loginStep1Result(false, "服务器返回的盐值格式错误");
                break;
            }
            emit loginStep1Result(true, "请输入密码", fullSalt); // 改为专用信号
            break;
        }
        case TASK_TYPE_LOGIN_SECTION1_RESP_ERROR: {
            QJsonDocument doc = QJsonDocument::fromJson(data);
            QString errorMsg = "登录失败";
            if (!doc.isNull() && doc.isObject()) {
                errorMsg = doc.object()["error"].toString("用户名不存在");
            }
            emit loginStep1Result(false, errorMsg); // 改为专用信号
            break;
        }
        case TASK_TYPE_LOGIN_SECTION2_RESP_OK:
            parseLoginStep2Response(data);
            break;
        case TASK_TYPE_LOGIN_SECTION2_RESP_ERROR:
            emit loginStep2Result(false, "密码错误"); // 改为专用信号
            break;
            //视频流
        case TASK_TYPE_STREAM_START_RESPONSE:
            parseStreamResponse(data);
            break;
            //PTZ请求
        case TASK_TYPE_PTZ_CONTROL_RESPONSE:
            parsePTZControlResponse(data);
            break;
        case TASK_TYPE_STREAM_METADATA: {
            // 检查数据有效性
            if (data.isEmpty()) {
                qWarning() << "接收到空的元数据";
                break;
            }

            try {
                // 添加详细的调试信息
                qDebug() << "元数据原始长度:" << data.size();
                qDebug() << "元数据前16字节:" << data.left(16).toHex();

                VideoMetadata metadata = deserializeMetadata(data);

                // 验证元数据关键字段
                if (metadata.width <= 0 || metadata.height <= 0) {
                    qWarning() << "无效的元数据 - 分辨率:" << metadata.width << "x" << metadata.height;
                    break;
                }

                if (metadata.codecId <= 0) {
                    qWarning() << "无效的编解码器ID:" << metadata.codecId;
                    break;
                }

                qDebug() << "成功解析元数据 - 摄像头:" << metadata.cameraId
                         << ", 分辨率:" << metadata.width << "x" << metadata.height
                         << ", 编码格式:" << metadata.codecId
                         << ", SPS/PPS大小:" << metadata.spsPps.size();

                emit metadataReceived(metadata);
            } catch (const std::exception& e) {
                qWarning() << "解析元数据失败:" << e.what();
                qDebug() << "错误数据:" << data.toHex();
            }
            break;
        }

        case TASK_TYPE_STREAM_DATA: {
            // 检查数据有效性
            if (data.isEmpty()) {
                qWarning() << "接收到空的视频帧数据";
                break;
            }

            try {
                // 添加调试信息
                qDebug() << "视频帧数据长度:" << data.size();
                if (data.size() > 16) {
                    qDebug() << "帧数据前16字节:" << data.left(16).toHex();
                }

                VideoFrame frame = deserializeVideoFrame(data);

                // 验证帧数据关键字段
                if (frame.cameraId <0) {
                    qWarning() << "无效的摄像头ID:" << frame.cameraId;
                    break;
                }

                if (frame.size <= 0 || frame.size > 10 * 1024 * 1024) { // 合理范围检查
                    qWarning() << "无效的帧大小:" << frame.size;
                    break;
                }

                if (frame.data.size() != frame.size) {
                    qWarning() << "帧数据大小不匹配, 声明:" << frame.size << "实际:" << frame.data.size();
                    break;
                }

                qDebug() << "成功解析视频帧 - 摄像头:" << frame.cameraId
                         << ", 大小:" << frame.size
                         << ", PTS:" << frame.pts
                         << ", DTS:" << frame.dts;

                emit videoFrameReceived(frame);
            } catch (const std::exception& e) {
                qWarning() << "视频帧解析失败:" << e.what();
                qDebug() << "错误数据长度:" << data.size();
                if (data.size() > 0) {
                    qDebug() << "错误数据开头:" << data.left(qMin(32, data.size())).toHex();
                }
            }
            break;
        }

        default:
            qDebug() << "未知消息类型:" << type;
            break;
        }
    }
}

//解析视频流的响应
void tcpclient::parseStreamResponse(const QByteArray &data)
{
    qDebug() << "解析视频流响应，原始数据:" << data;
    QJsonDocument doc=QJsonDocument::fromJson(data);
    if(doc.isNull()||!doc.isObject())
    {
        qDebug() << "解析JSON失败，数据格式不正确";
        emit streamUrlReceived(m_currentRequestChannel,false,"");
        return;
    }
    QJsonObject json = doc.object();
    int cameraId = json["camera_id"].toInt(-1);
    QString streamType = json["stream_type"].toString();
    QString url = json["url"].toString();

    bool isMainStream = (streamType == "main");
    qDebug() << "解析结果 - 摄像头ID:" << cameraId
             << "流类型:" <<  streamType
             << "URL:" << url;

    if (url.isEmpty()) {
        qDebug() << "警告: 服务器返回的URL为空";
    }

    // 使用保存的请求通道号而不是可能为-1的cameraId
    emit streamUrlReceived(m_currentRequestChannel, isMainStream, url);
}

void tcpclient::onError(QAbstractSocket::SocketError err) {
    emit connectError(m_socket.errorString());
}

// 解析云台控制响应
void tcpclient::parsePTZControlResponse(const QByteArray &data)
{
    //    qDebug() << "解析云台控制响应";
    //    QJsonDocument doc = QJsonDocument::fromJson(data);
    //    if (doc.isNull() || !doc.isObject()) {
    //        emit ptzControlResult(false, "无效的响应格式");
    //        return;
    //    }

    //    QJsonObject json = doc.object();
    //    bool success = json["success"].toBool(false);
    //    QString msg = json["message"].toString("未知错误");

    //    emit ptzControlResult(success, msg);

    qDebug() << "解析云台控制响应，原始数据:" << data;

    // 先尝试解析JSON
    QJsonDocument doc = QJsonDocument::fromJson(data);
    if (!doc.isNull() && doc.isObject()) {
        QJsonObject json = doc.object();
        bool success = json["success"].toBool(false);
        QString msg = json["message"].toString(success ? "操作成功" : "操作失败");

        qDebug() << "JSON解析结果 - 成功:" << success << "消息:" << msg;
        emit ptzControlResult(success, msg);
        return;
    }

    // 如果不是JSON，尝试解析纯文本
    QString responseText = QString::fromUtf8(data).trimmed();
    qDebug() << "非JSON响应，文本内容:" << responseText;

    // 检查响应文本中是否包含成功关键词
    if (responseText.contains("success", Qt::CaseInsensitive) ||
            responseText.contains("ok", Qt::CaseInsensitive) ||
            responseText.isEmpty()) { // 空响应也视为成功
        emit ptzControlResult(true, "操作成功");
    } else {
        // 如果响应文本包含错误信息，直接使用
        emit ptzControlResult(false, responseText.isEmpty() ? "未知错误" : responseText);
    }
}

void tcpclient::parseRegisterStep1Response(const QByteArray &data) {
    // 直接解析盐值，而不是期望JSON格式
    QString salt = QString::fromUtf8(data);

    if (salt.isEmpty() || !salt.startsWith("$1$")) {
        emit registerStep1Result(false, "服务器返回的盐值格式错误");
        return;
    }

    // 提取纯盐值部分（去掉$1$和结尾的$）
    QString pureSalt = salt.mid(3); // 去掉"$1$"
    int dollarPos = pureSalt.indexOf('$');
    if (dollarPos != -1) {
        pureSalt = pureSalt.left(dollarPos); // 去掉结尾的"$"
    }


    if (pureSalt.isEmpty()) {
        emit registerStep1Result(false, "无法解析盐值");
        return;
    }

    // 自动触发注册第二步
    QString encryptedPassword = generateMd5WithSalt(m_tempRegisterPassword, pureSalt);
    sendRegisterStep2(encryptedPassword);

    // 可以发送成功信号，或者等待第二步结果
    emit registerStep1Result(true, "获取盐值成功", QString::fromUtf8(data));
}

// tcpclient.cpp - 修改parseRegisterStep2Response函数
void tcpclient::parseRegisterStep2Response(const QByteArray &data) {
    // 先尝试解析JSON
    QJsonDocument doc = QJsonDocument::fromJson(data);
    if (!doc.isNull() && doc.isObject()) {
        QJsonObject json = doc.object();
        bool success = json["success"].toBool(false);
        QString msg = json["message"].toString(success ? "注册成功" : "注册失败");
        emit registerStep2Result(success, msg);
        return;
    }

    // 如果不是JSON，尝试解析纯文本
    QString responseText = QString::fromUtf8(data);
    if (responseText.contains("success", Qt::CaseInsensitive) ||
            responseText.contains("Register", Qt::CaseInsensitive)) {
        emit registerStep2Result(true, "注册成功");
    } else {
        emit registerStep2Result(false, responseText.isEmpty() ? "注册失败" : responseText);
    }
}

void tcpclient::parseLoginStep1Response(const QByteArray &data) {
    QJsonDocument doc = QJsonDocument::fromJson(data);
    if (doc.isNull() || !doc.isObject()) {
        emit loginStep1Result(false, "服务器响应格式错误");
        return;
    }
    QJsonObject json = doc.object();
    // 登录第一步成功通常返回salt用于第二步加密
    QString salt = json["salt"].toString();
    emit loginStep1Result(true, "请输入密码", salt);
}

void tcpclient::parseLoginStep2Response(const QByteArray &data)
{
    // 先尝试解析JSON
    QJsonDocument doc = QJsonDocument::fromJson(data);
    if (!doc.isNull() && doc.isObject()) {
        QJsonObject json = doc.object();
        bool success = json["success"].toBool(false);
        QString msg = json["message"].toString(success ? "登录成功" : "登录失败");
        emit loginStep2Result(success, msg); // 改为专用信号
        return;
    }

    // 如果不是JSON，尝试解析纯文本
    QString responseText = QString::fromUtf8(data);
    if (responseText.contains("success", Qt::CaseInsensitive) ||
            responseText.contains("Login", Qt::CaseInsensitive)) {
        emit loginStep2Result(true, "登录成功"); // 改为专用信号
    } else {
        emit loginStep2Result(false, responseText.isEmpty() ? "登录失败" : responseText); // 改为专用信号
    }
}

QString tcpclient::generateMd5WithSalt(const QString &password, const QString &salt) {
    qDebug() << "加密参数 - 密码:" << password;
    qDebug() << "加密参数 - 完整盐值:" << salt;

    // 计算 md5(salt + password)
    QByteArray srcData = (salt + password).toUtf8();
    QByteArray md5Hash = QCryptographicHash::hash(srcData, QCryptographicHash::Md5).toHex();

    // 格式：$1$salt$ + 哈希值（取前22位？根据服务器要求调整）
    QString result = QString("$1$%1$%2").arg(salt.mid(3, salt.length() - 4)).arg(QString(md5Hash).left(22));
    qDebug() << "加密结果:" << result;

    return result;
}
